﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

using System.DirectoryServices.AccountManagement;

namespace MailboxRightsLookup
{
    public partial class SearchForm : Form
    {
        DomainUtils _domainUtils;
        ReverseSearcher _searcher;

        public SearchForm()
        {
            InitializeComponent();
            nameValue.Text = guidValue.Text = domainValue.Text = accountValue.Text = sidValue.Text = "";

            _domainUtils = DomainUtils.Instance;
            _searcher = new ReverseSearcher(indexWorker);
            indexWorker.RunWorkerAsync(_searcher);
            toolStripStatusLabel.Text = "Indexing mailbox permissions";
        }

        private void searchButton_Click(object sender, EventArgs e)
        {
            string domain, account;
            UserPrincipal user;
            try
            {
                string[] searchStrings = searchText.Text.Split(new char[] { '\\' });
                domain = searchStrings[0].ToUpper();
                account = searchStrings[1].ToUpper();
                PrincipalContext context = _domainUtils.GetPrincipalContext(domain, DomainUtils.DomainNameType.Netbios);
                user = UserPrincipal.FindByIdentity(context, IdentityType.SamAccountName, account);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
                return;
            }

            if (user == null)
            {
                MessageBox.Show("User not found");
                return;
            }

            string sid = user.Sid.ToString();
            nameValue.Text = user.Name;
            guidValue.Text = user.Guid.ToString();
            domainValue.Text = domain;
            accountValue.Text = user.SamAccountName;
            sidValue.Text = sid;

            SortableBindingList<MailboxPermissionDetails> result = new SortableBindingList<MailboxPermissionDetails>();
            // Load direct permissions
            MailboxPermissionDetails permissionDetails;
            foreach (var directPermission in _searcher.GetUserPermissions(user.Sid))
            {
                permissionDetails = new MailboxPermissionDetails(directPermission);
                permissionDetails.direct = true;
                result.Add(permissionDetails);
            }
            // Load permissions through group membership
            foreach (var group in user.GetGroups())
            {
                foreach (var groupPermission in _searcher.GetUserPermissions(group.Sid))
                {
                    permissionDetails = new MailboxPermissionDetails(groupPermission);
                    permissionDetails.direct = false;
                    permissionDetails.throughGroup = group.Name;
                    result.Add(permissionDetails);
                }
            }
            mailboxPermissionBindingSource.DataSource = result;
        }

        private void indexWorker_DoWork(object sender, DoWorkEventArgs e)
        {
            ReverseSearcher searcher = e.Argument as ReverseSearcher;
            e.Result = searcher.CreateIndex();
        }

        private void indexWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            toolStripProgressBar.Value = 0;

            if (e.Error != null)
            {
                MessageBox.Show(RecurseExceptionMessages(e.Error, new StringBuilder()).ToString(), "Error");
                toolStripStatusLabel.Text = "ERROR: Could not create index";
            }
            else
            {
                toolStripStatusLabel.Text = e.Result as string;
                searchText.Enabled = true;
                searchButton.Enabled = true;
            }
        }

        private void indexWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            toolStripProgressBar.Value = e.ProgressPercentage;
            toolStripStatusLabel.Text = e.UserState.ToString();
        }

        private StringBuilder RecurseExceptionMessages(Exception ex, StringBuilder sb)
        {
            sb.AppendLine(ex.Message);
            if (ex.InnerException != null)
                RecurseExceptionMessages(ex.InnerException, sb);
            return sb;
        }

    }
}
